`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2025/11/06 19:16:26
// Design Name: 
// Module Name: tb_npu
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module tb_npu();
    reg clk;
    reg rst_n;
    reg start_npu;
    reg data_input_end;
    reg [7:0] data_in;
    wire [7:0] data_out;
    wire done_npu;
    wire state_input_monitor;

    npu uut (
        .clk(clk),
        .rst_n(rst_n),
        .start_npu(start_npu),
        .data_input_end(data_input_end),
        .data_in(data_in),
        .data_out(data_out),
        .done_npu(done_npu),
        .state_input_monitor(state_input_monitor)
    );

    initial begin
        clk = 0;
        forever #5 clk = ~clk; // 10ns时钟周期
    end

    integer file_fc1;
    integer file_fc2;
    integer file_fc3;
    integer file_result;

    // 每轮输出计数器：0 ~ 161（共162个）
    reg [7:0] cnt = 0; // 8位足够（162 < 256）

    initial begin
        // 打开四个输出文件
        file_fc1 = $fopen("D:/Verilog/LAB7/fc1_output.txt", "w");
        file_fc2 = $fopen("D:/Verilog/LAB7/fc2_output.txt", "w");
        file_fc3 = $fopen("D:/Verilog/LAB7/fc3_output.txt", "w");
        file_result = $fopen("D:/Verilog/LAB7/result.txt", "w");

        if (!file_fc1 || !file_fc2 || !file_fc3 || !file_result) begin
            $display("%t: ERROR: Cannot open output files.", $time);
            $finish;
        end
    end

    // !暂时的修改,rd_en_output快了一个时钟周期且长了一个时钟周期
    reg rd_en_dly;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n)
            rd_en_dly <= 1'b0;
        else
            rd_en_dly <= uut.rd_en_output;
    end

    wire rd_en_output_corrected = rd_en_dly && uut.rd_en_output;

    always @(posedge clk) begin
        if (rd_en_output_corrected) begin
            if (cnt < 128) begin
                // FC1 输出
                $fwrite(file_fc1, "%d\n", $signed(data_out));
            end else if (cnt < 160) begin
                // FC2 输出
                $fwrite(file_fc2, "%d\n", $signed(data_out));
            end else begin
                // FC3 输出
                $fwrite(file_fc3, "%d\n", $signed(data_out));
            end
            
            // 更新计数器（循环）
            if (cnt == 161) begin
                cnt <= 0;
            end else begin
                cnt <= cnt + 1;
            end
        end
    end

    // 额外：保存 FC3 的两个值并写入 result
    reg signed [7:0] fc3_val0, fc3_val1;
    reg in_fc3_phase = 0;

    always @(posedge clk) begin
        if (uut.rd_en_output) begin
            if (cnt == 160) begin
                fc3_val0 <= $signed(data_out);
            end else if (cnt == 161) begin
                fc3_val1 <= $signed(data_out);
                // 写入比较结果
                #10;
                if (fc3_val0 >= fc3_val1) begin
                    $fwrite(file_result, "0\n");
                end else begin
                    $fwrite(file_result, "1\n");
                end
            end
        end
    end

    integer file_handle;
    integer r;
    initial begin : data_read
        rst_n = 0;
        start_npu = 0;
        data_input_end = 0;
        data_in = 8'b0;

        #20;
        rst_n = 1;
        #10;
        start_npu = 1;
        #20;
        start_npu = 0;

        // 从D:\Verilog\LAB7\512.txt读取数据
        file_handle = $fopen("D:/Verilog/LAB7/21504.txt", "r");
        if (file_handle == 0) begin
            $display("Failed to open file.");
            $finish;
        end

        // 直接监控uut.wren_input_ram信号
        forever begin
            @(posedge clk);
            if (uut.wr_en_input) begin
                // 读取一行数据
                r = $fscanf(file_handle, "%b\n", data_in);
                if (r != 1) begin
                    $display("End of file reached or read error.");
                    data_input_end = 1;
                    @(posedge clk);
                    #10;
                    $fclose(file_handle);
                    disable data_read;
                end
            end
        end
    end

    initial begin
        // 等待仿真结束后关闭文件
        wait(done_npu);
        #10;
        $fclose(file_fc1);
        $fclose(file_fc2);
        $fclose(file_fc3);
        $fclose(file_result);
        $finish;
    end


endmodule
